/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 *
 * @author Martin
 */
import cern.jet.math.Bessel;
import java.lang.Math;

public class Circle {

    private double lambda = 0.0000005;
    private double z = 1.00;
    private double a = 0.0001;
    private double zoom = 0.00003;
    private double exposition = 5.0;

    public double getIntensity(int x, int y) {
        if (x == 0 && y == 0) {
            return 1.0;
        }

        //System.out.println("lambda" + lambda);
        //System.out.println("z " + z);
        //System.out.println("a " + a);
        //System.out.println("zoom " + zoom);
        //System.out.println("exposition " + exposition);


        double dx = x * getZoom();
        double dy = y * getZoom();
        double intensity;
        double xy;
        double O;
        double sc;
        double k;


        xy = Math.pow(Math.pow(dx, 2) + Math.pow(dy, 2), 0.5);
        k = 2 * Math.PI / lambda;
        O = Math.atan(xy / getZ());


        sc = (k * a * Math.sin(O));
        //Besselova funkce se pocita pomoci knihovny colt
        intensity = getExposition() * Math.pow(
                (2 * Bessel.j1(sc))
                / (sc), 2);


        //intensity = getExposition() * Math.pow(Math.sin(k * getA() * Math.sin(O)) / (k * getA() * Math.sin(O)), 2);

        return intensity;
    }

    private double Bessel1(double x) {
        int cycles = 50;
        int m;
        double bessel = 0;

        for (m = 0; m < cycles; m++) {
            bessel += (Math.pow(-1, m))
                    / (Fact(m) * GammaF(m + 1 + 1))
                    * (Math.pow(x / 2, 2 * m + 1));
        }

        return bessel;
    }

    private double GammaF(double x) {
        return Fact((int) (x) - 1);
    }

    private double Fact(int x) {
        double fact = 1;

        while (x > 0) {
            fact *= x;
            x--;
        }

        return fact;
    }

    public double airy() {
        return 1.22 * lambda / a;
    }

    //zoomuje tak, ze je airyho disk vzdy stejne velky -> nejdou videt rozdily v nastaveni
    public void setAutoZoom() {
        zoom = z * Math.tan(airy()) * 0.01;
    }

    /**
     * @return the zoom
     */
    public double getZoom() {
        return zoom;
    }

    /**
     * @param zoom the zoom to set
     */
    public void setZoom(double zoom) {
        this.zoom = zoom;
    }

    /**
     * @return the z
     */
    public double getZ() {
        return z;
    }

    /**
     * @param z the z to set
     */
    public void setZ(double z) {
        this.z = z;
    }

    /**
     * @return the a
     */
    public double getA() {
        return a;
    }

    /**
     * @param a the a to set
     */
    public void setA(double a) {
        this.a = a;
    }

    /**
     * @return the lambda
     */
    public double getLambda() {
        return lambda;
    }

    /**
     * @param lambda the lambda to set
     */
    public void setLambda(double lambda) {
        this.lambda = lambda;
    }

    /**
     * @return the exposition
     */
    public double getExposition() {
        return exposition;
    }

    /**
     * @param exposition the exposition to set
     */
    public void setExposition(double exposition) {
        this.exposition = exposition;
    }
}
